package com.an.blog.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.an.blog.admin.domain.BlogTalk;
import com.an.blog.admin.domain.bo.BlogTalkBo;
import com.an.blog.admin.domain.vo.BlogTalkVo;
import com.an.blog.mapper.BlogTalkMapper;
import com.an.blog.service.IBlogTalkService;
import com.an.blog.web.domain.vo.BlogTalkWebVo;
import com.an.common.constant.BlogConstants;
import com.an.common.core.domain.BaseEntity;
import com.an.common.core.domain.PageQuery;
import com.an.common.core.domain.entity.SysUser;
import com.an.common.core.page.TableDataInfo;
import com.an.common.core.service.OssService;
import com.an.common.utils.StreamUtils;
import com.an.common.utils.StringUtils;
import com.an.system.mapper.SysUserMapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

/**
 * 博客说说Service业务层处理
 *
 * @author Ann
 * @date 2023-05-08
 */
@RequiredArgsConstructor
@Service
public class BlogTalkServiceImpl implements IBlogTalkService {

    private final BlogTalkMapper baseMapper;
    private final OssService ossService;
    private final SysUserMapper userMapper;

    /**
     * 查询博客说说
     */
    @Override
    public BlogTalkVo queryById(Long talkId) {
        return baseMapper.selectVoById(talkId);
    }

    /**
     * 查询博客说说列表
     *
     * @param bo        业务对象
     * @param pageQuery 页面查询
     * @return {@link TableDataInfo }<{@link BlogTalkVo }>
     * @author: Ann
     * @createDate: 2023/05/10 16:03:54
     * @version: 1.0.0
     */
    @Override
    public TableDataInfo<BlogTalkVo> queryPageList(BlogTalkBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<BlogTalk> lqw = buildQueryWrapper(bo);
        Page<BlogTalkVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        //防止多次查询
        //查询所有涉及到的 oss 记录
        List<BlogTalkVo> records = result.getRecords();
        List<CompletableFuture<Void>> futures = new ArrayList<>();
        for (BlogTalkVo record : records) {
            CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
                String urls = ossService.selectUrlByIds(record.getTalkImage());
                record.setTalkImageUrl(urls);
            });
            futures.add(future);
        }
        CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join();
        return TableDataInfo.build(result);
    }

    /**
     * 查询博客说说列表
     *
     * @param bo 业务对象
     * @return {@link List }<{@link BlogTalkVo }>
     * @author: Ann
     * @createDate: 2023/05/10 13:50:10
     * @version: 1.0.0
     */
    @Override
    public List<BlogTalkVo> queryList(BlogTalkBo bo) {
        LambdaQueryWrapper<BlogTalk> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    /**
     * 建立查询包装
     *
     * @param bo 业务对象
     * @return {@link LambdaQueryWrapper }<{@link BlogTalk }>
     * @author: Ann
     * @createDate: 2023/05/10 13:50:09
     * @version: 1.0.0
     */
    private LambdaQueryWrapper<BlogTalk> buildQueryWrapper(BlogTalkBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<BlogTalk> lqw = Wrappers.lambdaQuery();
        lqw.like(StringUtils.isNotBlank(bo.getTalkContent()), BlogTalk::getTalkContent, bo.getTalkContent());
        lqw.eq(StringUtils.isNotBlank(bo.getStatus()), BlogTalk::getStatus, bo.getStatus());
        lqw.orderByDesc(BaseEntity::getCreateTime);
        return lqw;
    }

    /**
     * 新增博客说说
     */
    @Override
    public Boolean insertByBo(BlogTalkBo bo) {
        BlogTalk add = BeanUtil.toBean(bo, BlogTalk.class);
        validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setTalkId(add.getTalkId());
        }
        return flag;
    }

    /**
     * 修改博客说说
     */
    @Override
    public Boolean updateByBo(BlogTalkBo bo) {
        BlogTalk update = BeanUtil.toBean(bo, BlogTalk.class);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(BlogTalk entity) {
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 批量删除博客说说
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if (isValid) {
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteBatchIds(ids) > 0;
    }

    @Override
    public int updateArticleStatus(BlogTalkBo bo) {
        BlogTalk blogTalk = BeanUtil.toBean(bo, BlogTalk.class);
        return baseMapper.updateById(blogTalk);
    }

    /**
     * 更新文章是顶级
     *
     * @param bo 业务对象
     * @return int
     * @author: Ann
     * @createDate: 2023/05/10 17:11:12
     * @version: 1.0.0
     */
    @Override
    public int updateArticleIsTop(BlogTalkBo bo) {
        BlogTalk blogTalk = BeanUtil.toBean(bo, BlogTalk.class);
        return baseMapper.updateById(blogTalk);
    }

    /**
     * 查询和网络列表
     *
     * @param pageQuery 页面查询
     * @return {@link TableDataInfo }<{@link BlogTalkWebVo }>
     * @author: Ann
     * @createDate: 2023/08/16 10:53:31
     * @version: 1.0.0
     */
    @Override
    public TableDataInfo<BlogTalkWebVo> queryTalkWebList(PageQuery pageQuery) {
        Page<BlogTalk> blogTalkPage = baseMapper.selectPage(pageQuery.build(),
            new LambdaQueryWrapper<BlogTalk>().select(BlogTalk::getTalkId,
                BlogTalk::getTalkContent,
                BlogTalk::getTalkImage,
                BlogTalk::getIsTop,
                BaseEntity::getCreateBy,
                BaseEntity::getUpdateTime).eq(BlogTalk::getStatus, BlogConstants.NORMAL)
                .orderByDesc(BlogTalk::getIsTop)
                .orderByDesc(BaseEntity::getUpdateTime)
        );
        long total = blogTalkPage.getTotal();
        List<BlogTalk> blogTalks = blogTalkPage.getRecords();
        if(total==0L){
            return TableDataInfo.build(Collections.emptyList(),total);
        }
        List<String> userNames = StreamUtils.toList(blogTalks, BaseEntity::getCreateBy);
        List<SysUser> users = userMapper.selectList(new LambdaQueryWrapper<SysUser>().select(SysUser::getUserName,
                SysUser::getNickName,
                SysUser::getAvatar)
            .in(SysUser::getUserName, userNames));
        Map<String, String> userNameAvatarMap = StreamUtils.groupByKey2StringValue(users, SysUser::getUserName, SysUser::getAvatar);
        Map<String, String> userNameNickNameMap = StreamUtils.groupByKey2StringValue(users, SysUser::getUserName, SysUser::getNickName);

        List<BlogTalkWebVo> talks = blogTalks.stream().map(blogTalk -> {
            BlogTalkWebVo blogTalkWebVo = new BlogTalkWebVo();
            blogTalkWebVo.setTalkId(blogTalk.getTalkId());
            blogTalkWebVo.setTalkContent(blogTalk.getTalkContent());
            String imagesUrl = ossService.selectUrlByIds(blogTalk.getTalkImage());
            if(StringUtils.isNotBlank(imagesUrl)){
                blogTalkWebVo.setTalkImage(imagesUrl.split(","));
            }
            blogTalkWebVo.setIsTop(blogTalk.getIsTop());
            blogTalkWebVo.setCreateBy(userNameNickNameMap.get(blogTalk.getCreateBy()));
            blogTalkWebVo.setAvatar(userNameAvatarMap.get(blogTalk.getCreateBy()));
            blogTalkWebVo.setUpdateTime(blogTalk.getUpdateTime());
            return blogTalkWebVo;
        }).collect(Collectors.toList());
        return TableDataInfo.build(talks,total);
    }
}
